package com.clear.honghefinance.biz.modules.currency.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.clear.honghefinance.biz.modules.system.member.domain.vo.AdminDTO;
import com.clear.honghefinance.biz.modules.currency.converter.CurrencyConfigConverter;
import com.clear.honghefinance.biz.modules.currency.domain.dto.CreateCurrencyConfigDTO;
import com.clear.honghefinance.biz.modules.currency.domain.dto.DeleteCurrencyConfigDTO;
import com.clear.honghefinance.biz.modules.currency.domain.dto.UpdateCurrencyConfigDTO;
import com.clear.honghefinance.biz.modules.currency.domain.dto.UpdateCurrencyConfigStateDTO;
import com.clear.honghefinance.biz.modules.currency.domain.entity.CurrencyConfig;
import com.clear.honghefinance.biz.modules.currency.domain.vo.GetCurrencyConfigDetailVO;
import com.clear.honghefinance.biz.modules.currency.domain.vo.ListCurrencyConfigVO;
import com.clear.honghefinance.biz.modules.currency.mapper.CurrencyConfigMapper;
import com.clear.honghefinance.biz.modules.currency.service.ICurrencyConfigService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clear.honghefinance.common.exception.BizException;
import com.clear.honghefinance.common.service.TokenService;
import com.clear.honghefinance.common.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 货币配置 服务实现类
 * </p>
 *
 * @author 程序员clear
 * @since 2024-08-21
 */
@Service
@Slf4j
public class CurrencyConfigServiceImpl extends ServiceImpl<CurrencyConfigMapper, CurrencyConfig> implements ICurrencyConfigService {

    @Resource
    private TokenService<AdminDTO> tokenService;

    /**
     * 创建币别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean create(CreateCurrencyConfigDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("创建币别中，入参：{}", JSON.toJSONString(dto));
        }
        GetCurrencyConfigDetailVO currencyConfigDetailVO = this.getByCode(dto.getCode());
        if (currencyConfigDetailVO != null) {
            throw new BizException("币别已存在");
        }
        try {
            CurrencyConfig currencyConfig = CurrencyConfigConverter.INSTANCE.convertDTOToCurrencyConfigEntity(dto);
            currencyConfig.setMemberId(tokenService.getThreadLocalUserId());
            currencyConfig.setTenantId(tokenService.getThreadLocalTenantId());
            currencyConfig.initDefault();

            return this.save(currencyConfig);
        } catch (Exception e) {
            log.error("创建币别异常 {}", e.getMessage(), e);
            throw new BizException("创建币别异常");
        }
    }

    /**
     * 修改币别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean update(UpdateCurrencyConfigDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("编辑币别中，入参：{}", JSON.toJSONString(dto));
        }
        GetCurrencyConfigDetailVO currencyConfigDetailVO = this.getByCode(dto.getCode());
        // 币别已存在，不能重复
        if (currencyConfigDetailVO != null && !Objects.equals(dto.getId(), currencyConfigDetailVO.getId())) {
            throw new BizException("币别已存在");
        }
        try {
            CurrencyConfig currencyConfig = CurrencyConfigConverter.INSTANCE.convertDTOToCurrencyConfigEntity(dto);
            currencyConfig.setUpdateMemberId(tokenService.getThreadLocalUserId());
            currencyConfig.setUpdateTime(DateUtil.getSystemTime());

            LambdaUpdateWrapper<CurrencyConfig> lambdaUpdateWrapper = Wrappers.<CurrencyConfig>lambdaUpdate()
                    .eq(CurrencyConfig::getId, dto.getId())
                    // 只能修改当前租户下的币别
                    .eq(CurrencyConfig::getTenantId, tokenService.getThreadLocalTenantId());

            if (!this.update(currencyConfig, lambdaUpdateWrapper)) {
                throw new BizException("修改币别失败");
            }
        } catch (Exception e) {
            log.error("编辑币别异常 {}", e.getMessage(), e);
            throw new BizException("编辑币别异常");
        }
        return true;
    }

    /**
     * 禁用启用币别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean updateDisable(UpdateCurrencyConfigStateDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("{}币别中，入参：{}", dto.getDisable() ? "禁用" : "启用", JSON.toJSONString(dto));
        }
        try {
            LambdaUpdateWrapper<CurrencyConfig> lambdaUpdateWrapper = Wrappers.<CurrencyConfig>lambdaUpdate()
                    .eq(CurrencyConfig::getId, dto.getId())
                    .eq(CurrencyConfig::getDisable, !dto.getDisable())  // 状态与传入的不同才会改变
                    // 只改变未删除的币别的禁用状态
                    .eq(CurrencyConfig::getDelFlag, false)
                    .set(CurrencyConfig::getDisable, dto.getDisable())
                    .set(CurrencyConfig::getUpdateMemberId, tokenService.getThreadLocalUserId())
                    .set(CurrencyConfig::getUpdateTime, DateUtil.getSystemTime());

            if (this.update(lambdaUpdateWrapper)) {
                return true;
            } else {
                throw new BizException(String.format("%s币别异常", dto.getDisable() ? "禁用" : "启用"));
            }
        } catch (Exception e) {
            log.error("{}币别异常 {}", dto.getDisable() ? "禁用" : "启用", e.getMessage(), e);
            throw new BizException(String.format("%s币别异常", dto.getDisable() ? "禁用" : "启用"));
        }
    }

    /**
     * 删除币别
     *
     * @param dto
     * @return
     */
    @Override
    public boolean delete(DeleteCurrencyConfigDTO dto) {
        if (log.isInfoEnabled()) {
            log.info("删除币别中，入参：{}", JSON.toJSONString(dto));
        }
        try {
            LambdaUpdateWrapper<CurrencyConfig> lambdaUpdateWrapper = Wrappers.<CurrencyConfig>lambdaUpdate()
                    .eq(CurrencyConfig::getId, dto.getId())
                    .eq(CurrencyConfig::getDelFlag, false)
                    // 目前只能删除自己的币别
                    .eq(CurrencyConfig::getTenantId, tokenService.getThreadLocalTenantId())
                    // 只能删除未使用的币别
                    .eq(CurrencyConfig::getUseCount, 0)
                    // 只能删除未禁用的币别
                    .eq(CurrencyConfig::getDelFlag, false)
                    .set(CurrencyConfig::getDelFlag, true)
                    .set(CurrencyConfig::getUpdateMemberId, tokenService.getThreadLocalUserId())
                    .set(CurrencyConfig::getUpdateTime, DateUtil.getSystemTime());

            if (this.update(lambdaUpdateWrapper)) {
                return true;
            } else {
                if (log.isInfoEnabled()) {
                    log.info("删除币别异常，入参：{}", JSON.toJSONString(dto));
                }
                throw new BizException("删除币别异常");
            }
        } catch (Exception e) {
            log.error("删除币别异常 {}", e.getMessage(), e);
            throw new BizException("删除币别异常");
        }
    }

    /**
     * 根据id获取详情
     *
     * @param id
     * @return
     */
    @Override
    public GetCurrencyConfigDetailVO getDetailById(Long id) {
        log.info("查看币别明细中，入参：{}", id);
        try {
            LambdaQueryWrapper<CurrencyConfig> lambdaQueryWrapper = Wrappers.<CurrencyConfig>lambdaQuery()
                    .eq(CurrencyConfig::getId, id)
                    .eq(CurrencyConfig::getDelFlag, false)
                    // 只能查到当前租户的币别
                    .eq(CurrencyConfig::getTenantId, tokenService.getThreadLocalTenantId());
            CurrencyConfig currencyConfig = this.getOne(lambdaQueryWrapper);
            if (Objects.isNull(currencyConfig)) {
                throw new BizException("币别不存在");
            }
            return CurrencyConfigConverter.INSTANCE.convertCurrencyConfigEntityToGetCurrencyConfigDetailVO(currencyConfig);
        } catch (Exception e) {
            log.error("查看币别明细异常 {}", e.getMessage(), e);
            throw new BizException("查看币别明细异常");
        }
    }

    /**
     * 获取币别列表
     *
     * @return
     */
    @Override
    public List<ListCurrencyConfigVO> listAll() {

        log.info("查看币别列表中");

        try {
            LambdaQueryWrapper<CurrencyConfig> lambdaQueryWrapper = Wrappers.<CurrencyConfig>lambdaQuery()
                    .eq(CurrencyConfig::getDelFlag, false)
                    // 只能查到当前租户的币别
                    .eq(CurrencyConfig::getTenantId, tokenService.getThreadLocalTenantId())
                    // 根据是否是本位币降序
                    .orderByDesc(CurrencyConfig::getBaseCurrencyFlag)
                    // 根据编码升序
                    .orderByAsc(CurrencyConfig::getCode);

            List<CurrencyConfig> list = this.list(lambdaQueryWrapper);
            return CurrencyConfigConverter.INSTANCE.convertCurrencyConfigEntityToListCurrencyConfigVO(list);

        } catch (Exception e) {
            log.error("查询币别异常 {}", e.getMessage(), e);
            throw new BizException("查询币别异常");
        }
    }

    /**
     * 查询币别信息
     *
     * @param code
     * @return
     */
    private GetCurrencyConfigDetailVO getByCode(String code) {
        CurrencyConfig currency = this.getOne(Wrappers.<CurrencyConfig>lambdaQuery()
                .eq(CurrencyConfig::getCode, code)
                // 只能查到当前租户的币别
                .eq(CurrencyConfig::getTenantId, tokenService.getThreadLocalTenantId())
                .eq(CurrencyConfig::getDelFlag, false)
        );
        return CurrencyConfigConverter.INSTANCE.convertCurrencyConfigEntityToGetCurrencyConfigDetailVO(currency);
    }
}
